﻿using OThinker.Clusterware;
using OThinker.H3.Acl;
using OThinker.H3.Analytics.Reporting;
using OThinker.H3.Apps;
using OThinker.H3.DataModel;
using OThinker.Organization;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace OThinker.H3.Upgrade
{
    class Program
    {
        public static string ServerHost { get; set; }
        public static int Port { get; set; }
        public static string Account { get; set; }
        public static string Password { get; set; }
        public static string EngineName { get; set; }
        public static string ConnString = "Servers={0}:{1};User={2};Password={3};Engine={4}";


        static void Main(string[] args)
        {
            Console.WriteLine("正在连接到目标引擎实例.....");
            Connect();
            Console.WriteLine("开始升级.....");

            Console.WriteLine("升级系统欢迎页开始....");
            UpgradeWelcome();
            Console.WriteLine("升级系统欢迎页完成....");

            Console.WriteLine("升级系统设置开始....");
            UpgradeCustomSetting();
            Console.WriteLine("升级系统设置完成");

            Console.WriteLine("升级门户功能菜单开始....");
            UpgradeFunctionNode();
            Console.WriteLine("升级门户功能菜单完成");

            Console.WriteLine("升级功能菜单开始....");
            //UpdateFunctionCode();
            Console.WriteLine("升级功能菜单完成");

            Console.WriteLine("升级Schema开始.....");
            UpdateSchema();
            Console.WriteLine("升级Schema完成.");

            Console.WriteLine("升级组织开始.....");
            OrgUpgrade();
            Console.WriteLine("升级组织完成.");

            Console.WriteLine("升级应用中心开始.....");
            AppUpgrade();
            Console.WriteLine("升级应用中心完成.");

            Console.WriteLine("升级BPA开始.....");
            BPAUpgrade();
            Console.WriteLine("升级BPA完成.");

            Console.WriteLine("升级完成,请重启引擎服务和IIS站点.....");
            Console.ReadLine();
        }

        static void Connect()
        {
            Console.Write("请输入集群主服务器IP：");
            ServerHost = Console.ReadLine();
            Console.Write("请输入端口号：");
            int port = 0;
            while (!int.TryParse(Console.ReadLine(), out port))
            {
                Console.Write("请输入正确的端口号：");
                int.TryParse(Console.ReadLine(), out port);
            }
            Port = port;
            Console.Write("请输入需要升级的引擎实例名称：");
            EngineName = Console.ReadLine();
            Console.Write("请输入登录引擎实例服务的账号：");
            Account = Console.ReadLine();
            Console.Write("请输入登录引擎实例的密码：");
            Password = Console.ReadLine();
            try
            {
                string companyId = Engine.Organization.Company.CompanyID;
            }
            catch (Exception ex)
            {
                Console.WriteLine("连接失败:" + ex.Message);
                Connect();
            }
        }

        private static IEngine engine = null;
        static IEngine Engine
        {
            get
            {
                if (engine == null)
                {

                    OThinker.H3.Connection conn = new Connection();
                    conn.Open(string.Format(ConnString, ServerHost, Port, Account, Password, EngineName));
                    engine = conn.Engine;
                }
                return engine;
            }
        }

        static void UpgradeWelcome()
        {
            FunctionNode[] nodes = Engine.FunctionAclManager.GetFunctionNodesByParentCode(FunctionNode.Category_ServiceMoniter_Code);
            if (nodes != null)
            {
                foreach (FunctionNode node in nodes)
                {
                    if (node.Url.IndexOf(".html") > -1)
                    {
                        node.Url = node.Url.Replace(".html", ".aspx");
                        Engine.FunctionAclManager.UpdateFunctionNode(node);
                    }
                }
            }

            FunctionNode serviceNode = Engine.FunctionAclManager.GetFunctionNodeByCode(FunctionNode.Category_ServiceMoniter_Code);
            if (serviceNode != null)
            {
                if (serviceNode.Url.IndexOf(".html") > -1)
                {
                    serviceNode.Url = serviceNode.Url.Replace(".html", ".aspx");
                    Engine.FunctionAclManager.UpdateFunctionNode(serviceNode);
                }
            }
        }

        static void UpgradeCustomSetting()
        {
            string interavl = Engine.SettingManager.GetCustomSetting(OThinker.H3.Settings.CustomSetting.Setting_UnfinishedWorkItemRefreshInterval);
            if (string.IsNullOrEmpty(interavl) || interavl == "0")
            {
                Engine.SettingManager.SetCustomSetting(OThinker.H3.Settings.CustomSetting.Setting_UnfinishedWorkItemRefreshInterval, "1");
            }

            // 如果常规参数-帮助网站地址没有值，为其设置默认值
            string wikiUrl = Engine.SettingManager.GetCustomSetting(OThinker.H3.Settings.CustomSetting.Setting_WikiUrl);
            if (string.IsNullOrEmpty(wikiUrl))
            {
                Engine.SettingManager.SetCustomSetting(OThinker.H3.Settings.CustomSetting.Setting_WikiUrl, "http://wiki.h3yun.com/Default.aspx?code=");
            }
        }

        static bool UpdateSchema()
        {
            OThinker.Data.Database.Serialization.SerializerContainer container = new OThinker.Data.Database.Serialization.SerializerContainer(Engine.EngineConfig.CommandFactory);
            {
                container.AddSupportedType(typeof(OThinker.H3.DataModel.DraftBizObjectSchemaWrapper));
                OThinker.Data.Database.Serialization.Serializer serializer = container.GetSerializer(typeof(DraftBizObjectSchemaWrapper));
                DraftBizObjectSchemaWrapper[] schemas = serializer.GetAll<DraftBizObjectSchemaWrapper>();
                if (schemas != null)
                {
                    foreach (DraftBizObjectSchemaWrapper wrapper in schemas)
                    {
                        UpdateSchema(serializer, wrapper);
                    }
                }
            }
            {
                container.AddSupportedType(typeof(OThinker.H3.DataModel.PublishedBizObjectSchemaWrapper));
                OThinker.Data.Database.Serialization.Serializer serializer = container.GetSerializer(typeof(PublishedBizObjectSchemaWrapper));
                PublishedBizObjectSchemaWrapper[] schemas = serializer.GetAll<PublishedBizObjectSchemaWrapper>();
                if (schemas != null)
                {
                    foreach (PublishedBizObjectSchemaWrapper wrapper in schemas)
                    {
                        UpdateSchema(serializer, wrapper);
                    }
                }
            }
            return true;
        }

        static void UpdateSchema(OThinker.Data.Database.Serialization.Serializer serializer, DraftBizObjectSchemaWrapper wrapper)
        {
            OThinker.H3.DataModel.BizObjectSchema schema = wrapper.Content;
            if (schema.GetProperty(BizObjectSchema.PropertyName_OwnerId) == null)
            {
                schema.AddProperty(new DataModel.PropertySchema(BizObjectSchema.PropertyName_OwnerId,
                    BizObjectSchema.PropertyName_OwnerId,
                    Data.DataLogicType.String,
                    null));
            }
            if (schema.GetProperty(BizObjectSchema.PropertyName_OwnerParentId) == null)
            {
                schema.AddProperty(new DataModel.PropertySchema(BizObjectSchema.PropertyName_OwnerParentId,
                    BizObjectSchema.PropertyName_OwnerParentId,
                    Data.DataLogicType.String,
                    null));
            }
            if (schema.GetProperty(BizObjectSchema.PropertyName_RunningInstanceId) == null)
            {
                schema.AddProperty(new DataModel.PropertySchema(BizObjectSchema.PropertyName_RunningInstanceId,
                    BizObjectSchema.PropertyName_RunningInstanceId,
                    Data.DataLogicType.String,
                    null));
            }
            wrapper.SetPropertyDirty(DraftBizObjectSchemaWrapper.PropertyName_Content);
            serializer.Update(wrapper);
        }

        /// <summary>
        /// 重置菜单
        /// </summary>
        static void UpdateFunctionCode()
        {
            string[] defaultAppCodes = new string[] { FunctionNode.App_Workflow, FunctionNode.App_Report };
            foreach (string code in defaultAppCodes)
            {
                OThinker.H3.Acl.FunctionNode[] functionNodes = Engine.FunctionAclManager.GetFunctionNodesByParentCode(code);
                if (functionNodes != null)
                {
                    foreach (OThinker.H3.Acl.FunctionNode node in functionNodes)
                    {// 删除原有的菜单
                        Engine.FunctionAclManager.RemoveFunctionNode(node.ObjectID, true);
                    }
                }
            }

            // 执行初始化
            OThinker.Data.Database.Serialization.SerializerContainer container = new OThinker.Data.Database.Serialization.SerializerContainer(Engine.EngineConfig.CommandFactory);
            OThinker.H3.MenuInitializer.Initialize(container);
        }

        static void BPAUpgrade()
        {
            //更新原来的报表模板节点的类型，为报表目录
            OThinker.H3.Acl.FunctionNode node = Engine.FunctionAclManager.GetFunctionNodeByCode(OThinker.H3.Acl.FunctionNode.BPA_ReportTemplate_Code);
            if (node != null)
            {
                node.NodeType = OThinker.H3.Acl.FunctionNodeType.ReportTemplateFolder;
                Engine.FunctionAclManager.UpdateFunctionNode(node);
            }



            //更新已经存在的报表菜单节点
            OThinker.H3.Acl.FunctionNode[] nodes = Engine.FunctionAclManager.GetFunctionNodesByParentCode(OThinker.H3.Acl.FunctionNode.BPA_ReportTemplate_Code);
            if (nodes != null)
            {
                foreach (OThinker.H3.Acl.FunctionNode n in nodes)
                {
                    //如果父节点是报表节点的话，就删除
                    if (n.ParentCode == OThinker.H3.Acl.FunctionNode.BPA_ReportTemplate_Code
                        && n.NodeType == FunctionNodeType.BPAReportTemplate)
                    {
                        Engine.FunctionAclManager.RemoveFunctionNode(n.ObjectID, true);
                    }
                    //如果是应用中心里需要的节点，则更新显示地址
                    else if (n.Url == null || n.Url.IndexOf("ShowReport.aspx?Code=") < 0)
                    {
                        n.Url = "ShowReport.aspx?Code=" + n.Code;
                        Engine.FunctionAclManager.UpdateFunctionNode(n);
                    }
                }
            }

            //更新维度
            ReportTemplate report = Engine.Analyzer.GetReportTemplateByCode(FunctionNode.SystemReport_10001);
            if (report.AxisDimension == AxisDimension.RowTilte)
            {
                report.AxisDimension = AxisDimension.ColumnTitle;
                Engine.Analyzer.UpdateReportTemplate(report);
            }

            OThinker.Data.Database.CommandFactory command = new OThinker.Data.Database.CommandFactory(Engine.EngineConfig.DBType, Engine.EngineConfig.DBConnString);

            try
            {
                command.CreateCommand().ExecuteNonQuery("UPDATE OT_ReportTemplateParameter SET ParameterValue='1' where ColumnCode='ParentPid'");
                //数据源字段修改 RPSorceType-->ReportSorceType
                Dictionary<string, OThinker.Data.Database.DataColumn> Columns = command.CreateCommand().GetTableColumns("OT_ReportSource");
                if (Columns.ContainsKey("ReportSourceType") && Columns.ContainsKey("RPSorceType"))
                    command.CreateCommand().ExecuteNonQuery("UPDATE OT_ReportSource SET ReportSourceType=RPSorceType ");
                //OT_ReportTemplate 字段修改 AxiDimension-->AxisDimension
                Columns = command.CreateCommand().GetTableColumns("OT_ReportTemplate");
                if (Columns.ContainsKey("AxisDimension") && Columns.ContainsKey("AxiDimension"))
                    command.CreateCommand().ExecuteNonQuery("UPDATE OT_ReportTemplate SET AxisDimension=AxiDimension ");
                //过滤参数字段修改 ParameterVale-->ParameterValue;Visible->>Visible
                Columns = command.CreateCommand().GetTableColumns("OT_ReportTemplateParameter");
                if (Columns.ContainsKey("ParameterValue") && Columns.ContainsKey("ParameterVale") && Columns.ContainsKey("Visible") && Columns.ContainsKey("ISShow"))
                {
                    command.CreateCommand().ExecuteNonQuery("UPDATE OT_ReportTemplateParameter SET ParameterValue=ParameterVale,Visible=ISShow");
                }
            }
            catch (Exception e)
            {
            }

            //行列标题钻取参数 RowTitle->RowDrillParam ColumnTitle->ColumnDrillParam
            ReportTemplate[] reportTemplates = Engine.Analyzer.GetAllReportTemplates();
            foreach (ReportTemplate reportTemplate in reportTemplates)
            {
                if (!string.IsNullOrEmpty(reportTemplate.RowTitle) && reportTemplate.RowDrillParam == null)
                {
                    List<DrillParam> rowDrillParams = new List<DrillParam>();
                    string[] rowTitles = reportTemplate.RowTitle.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string rowTitle in rowTitles)
                    {
                        rowDrillParams.Add(new DrillParam() { Title = rowTitle, Code = rowTitle, Name = rowTitle });
                    }
                    reportTemplate.RowDrillParam = rowDrillParams.ToArray();
                }
                if (!string.IsNullOrEmpty(reportTemplate.ColumnTitle) && reportTemplate.ColumnDrillParam == null)
                {
                    reportTemplate.ColumnDrillParam = new DrillParam()
                    {
                        Title = reportTemplate.ColumnTitle,
                        Code = reportTemplate.ColumnTitle,
                        Name = reportTemplate.ColumnTitle
                    };
                }
                Engine.Analyzer.UpdateReportTemplate(reportTemplate);
            }

            #region 升级默认报表xy轴单位
            ReportTemplate systemReport_10001 = Engine.Analyzer.GetReportTemplateByCode(FunctionNode.SystemReport_10001);
            if (systemReport_10001 != null && string.IsNullOrEmpty(systemReport_10001.AxisUnit))
            {
                systemReport_10001.AxisUnit = "个";
                Engine.Analyzer.UpdateReportTemplate(systemReport_10001);
            }
            ReportTemplate systemReport_10002 = Engine.Analyzer.GetReportTemplateByCode(FunctionNode.SystemReport_10002);
            if (systemReport_10002 != null && string.IsNullOrEmpty(systemReport_10002.AxisUnit))
            {
                systemReport_10002.AxisUnit = "分钟";
                Engine.Analyzer.UpdateReportTemplate(systemReport_10002);
            }
            ReportTemplate systemReport_10003 = Engine.Analyzer.GetReportTemplateByCode(FunctionNode.SystemReport_10003);
            if (systemReport_10003 != null && string.IsNullOrEmpty(systemReport_10003.AxisUnit))
            {
                systemReport_10003.AxisUnit = "个";
                Engine.Analyzer.UpdateReportTemplate(systemReport_10003);
            }
            ReportTemplate systemReport_10004 = Engine.Analyzer.GetReportTemplateByCode(FunctionNode.SystemReport_10004);
            if (systemReport_10004 != null && string.IsNullOrEmpty(systemReport_10004.AxisUnit))
            {
                systemReport_10004.AxisUnit = "个";
                Engine.Analyzer.UpdateReportTemplate(systemReport_10004);
            }
            ReportTemplate systemReport_10005 = Engine.Analyzer.GetReportTemplateByCode(FunctionNode.SystemReport_10005);
            if (systemReport_10005 != null && string.IsNullOrEmpty(systemReport_10005.AxisUnit))
            {
                systemReport_10005.AxisUnit = "分钟";
                Engine.Analyzer.UpdateReportTemplate(systemReport_10005);
            }
            ReportTemplate systemReport_10006 = Engine.Analyzer.GetReportTemplateByCode(FunctionNode.SystemReport_10006);
            if (systemReport_10006 != null && string.IsNullOrEmpty(systemReport_10006.AxisUnit))
            {
                systemReport_10006.AxisUnit = "个";
                Engine.Analyzer.UpdateReportTemplate(systemReport_10006);
            }
            #endregion
        }

        static void OrgUpgrade()
        {
            //组织机构平铺
            Engine.Organization.InitOrganizationDim();
        }

        static void AppUpgrade()
        {
            //获取所有的应用
            AppNavigation[] apps = Engine.AppNavigationManager.GetAllApps();
            if (apps == null) return;
            foreach (AppNavigation app in apps)
            {
                //更新应用的菜单节点类型
                FunctionNode node = Engine.FunctionAclManager.GetFunctionNodeByCode(app.AppCode);
                if (node != null)
                {// 已经存在，只做更新
                    node.NodeType = FunctionNodeType.AppNavigation;
                    node.IconUrl = app.IconUrl;
                    node.SortKey = app.SortKey;
                    Engine.FunctionAclManager.UpdateFunctionNode(node);
                }
                else
                { // 做新增
                    node = new FunctionNode()
                    {
                        Code = app.AppCode,
                        DisplayName = app.DisplayName,
                        SortKey = app.SortKey,
                        IsSystem = false,
                        NodeType = FunctionNodeType.AppNavigation,
                        IconUrl = app.IconUrl
                    };
                    long res = Engine.FunctionAclManager.AddFunctionNode(node);
                    if (res != (long)HandleResult.SUCCESS)
                    {
                        Console.WriteLine(string.Format("新增应用中心节点：{0}失败，错误代码：{1}", app.AppCode, res));
                    }
                    else
                    {
                        FunctionAcl acl = new FunctionAcl(Engine.Organization.Company.ObjectID, app.AppCode, true, Organization.User.SystemUserID);
                    }
                }

                //更新应用菜单的节点类型
                FunctionNode[] childrenNodes = Engine.FunctionAclManager.GetFunctionNodesByParentCode(app.AppCode);
                UpgradAppMenu(childrenNodes);
            }
        }

        static void UpgradAppMenu(FunctionNode[] childrenNodes)
        {
            if (childrenNodes == null) return;
            foreach (FunctionNode c in childrenNodes)
            {
                c.NodeType = FunctionNodeType.AppMenu;
                Engine.FunctionAclManager.UpdateFunctionNode(c);
                UpgradAppMenu(Engine.FunctionAclManager.GetFunctionNodesByParentCode(c.Code));
            }
        }
        // End AppUpdate

        static void UpgradeFunctionNode()
        {
            FunctionNode Node = Engine.FunctionAclManager.GetFunctionNodeByCode(FunctionNode.BizBus_EditSAPConnectionConfig_Code);
            if (Node != null)
            {
                Node.Url = "BizBus/ListSAPConnectionConfig.aspx";
                Engine.FunctionAclManager.UpdateFunctionNode(Node);
            }

            Node = Engine.FunctionAclManager.GetFunctionNodeByCode(FunctionNode.Organization_QueryOrg_Code);
            if (Node != null)
            {
                Node.Url = "Organization/QueryUser.aspx";
                Engine.FunctionAclManager.UpdateFunctionNode(Node);
            }


            Node = Engine.FunctionAclManager.GetFunctionNodeByCode(FunctionNode.PersonalSetting_MyProfile_Code);
            if (Node != null)
            {
                Node.Url = "EditUser.aspx";
                Engine.FunctionAclManager.UpdateFunctionNode(Node);
            }
        }
    }
    // End Class
}
